﻿#include"FITKAcousticsSEAFaceMgrAdaptor.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEAFace.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsTriangles.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAFlatCurvedFace.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSysWithNodes.h"
#include "FITKAcousticsHDF5Writer.h"
#include "FITKAcousticsHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKHDF5FileTool.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementTri.h"

bool IO::FITKAcousticsSEAFaceMgrAdaptor::adaptR()
{
    Acoustics::FITKSEAFaceManager* FaceManagerP =
        dynamic_cast<Acoustics::FITKSEAFaceManager*>(_dataObj);
    if (FaceManagerP == nullptr || _reader == nullptr) return false;
    m_toolp = _reader->getHDF5FileTool();//初始化工具

    std::tuple<bool, H5::Group>Ret = m_toolp->openGp("Face");//打开Face组
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group gp = std::get<1>(Ret);

    return this->readFace(gp, FaceManagerP);
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::adaptW()
{
    Acoustics::FITKSEAFaceManager* FaceManagerP =
        dynamic_cast<Acoustics::FITKSEAFaceManager*>(_dataObj);
    if (FaceManagerP == nullptr || _writer == nullptr) return false;
    m_toolp = _writer->getHDF5FileTool();//初始化工具

    std::tuple<bool, H5::Group> Ret = m_toolp->createGp("Face");     //创建面组
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group gp = std::get<1>(Ret);

    return this->writeFace(gp, FaceManagerP);
}

Acoustics::FITKAbstractSEAFace * IO::FITKAcousticsSEAFaceMgrAdaptor::fromTypeCreateClass(H5::Group &gp, Acoustics::FITKAbstractSEASubSys::SEASubSysType faceType)
{
    switch (faceType)
    {
    case Acoustics::FITKAbstractSEASubSys::SEASSNone:
        break;
    case Acoustics::FITKAbstractSEASubSys::SEABeam:
    {
        Acoustics::FITKSEABeamFace *faceP = new Acoustics::FITKSEABeamFace;
        Acoustics::FITKAbstractSEAFace* P = dynamic_cast<Acoustics::FITKAbstractSEAFace*>(faceP);
        return P;
        break;
    }
    case Acoustics::FITKAbstractSEASubSys::SEAFlatPlate:
    {
        Acoustics::FITKSEAFlatPlateFace *faceP = new Acoustics::FITKSEAFlatPlateFace;
        Acoustics::FITKAbstractSEAFace* P = dynamic_cast<Acoustics::FITKAbstractSEAFace*>(faceP);
        return P;
        break;
    }
    case Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell:
    {
        Acoustics::FITKSEASinglyCurvedFace *faceP = new Acoustics::FITKSEASinglyCurvedFace;
        Acoustics::FITKAbstractSEAFace* P = dynamic_cast<Acoustics::FITKAbstractSEAFace*>(faceP);
        return P;
        break;
    }
    case Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell:
    {
        //双曲率板，需要单独设置一个数据
        int NumberOfRing = -1;
        m_toolp->readGroupint(gp, "NumberOfRing", &NumberOfRing);
        Acoustics::FITKSEADoublyCurvedFace *faceP = new Acoustics::FITKSEADoublyCurvedFace;
        if (faceP != nullptr)
        {
            faceP->setNumberOfRing(NumberOfRing);
        }
        Acoustics::FITKAbstractSEAFace* P = dynamic_cast<Acoustics::FITKAbstractSEAFace*>(faceP);
        return P;
        break;
    }
    case Acoustics::FITKAbstractSEASubSys::SEACylinderShell:
    {
        break;
    }
    case Acoustics::FITKAbstractSEASubSys::SEACavity:
    {
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEASemiIInfiniteFluid:
    {
        break;
    }
    default:
        break;
    }
    return nullptr;
}



bool IO::FITKAcousticsSEAFaceMgrAdaptor::readFace(H5::Group & gp, Acoustics::FITKSEAFaceManager * mager)
{
    std::tuple<bool, H5::Attribute>RetAttr = m_toolp->openAttribut(gp, "FaceDataCount"); //打开组个数属性
    if (std::get<0>(RetAttr) == false) { return false; }
    H5::Attribute CountAttrattr = std::get<1>(RetAttr);
    int count = -1;
    CountAttrattr.read(H5::PredType::NATIVE_INT, &count);

    for (int i = 0; i < count; i++)
    {
        QString number = QString::number(i);
        std::tuple<bool, H5::Group>Ret = m_toolp->openGp(gp, number.toStdString().data());//打开子节点
        if (std::get<0>(Ret) == false) { return false; }
        H5::Group subGroup = std::get<1>(Ret);

        Acoustics::FITKAbstractSEASubSys::SEASubSysType faceType = this->readTypeFace(subGroup);//获取类型

        Acoustics::FITKAbstractSEAFace *faceP = this->fromTypeCreateClass(subGroup, faceType);//根据类型创建子类,并强转回父类
        if (faceP == nullptr) { return false; }

        this->readNodes(subGroup, faceP);//读取面的节点列表

        this->readTriangleMesh(subGroup, faceP);//读面的三角型列表

        int isFEFace = false;//是否是使用 FE的面生成的
        int OutsideNCTID = -1;//外部声学包id
        int InsideNCTID = -1;//内部声学包id
        double OutsideNCTCoveredArea = 100.0;//外部声学包覆盖率 0-100
        double InsideNCTCoveredArea = 100.0;//内部声学包覆盖率 0-100
        int ID = -1;//DataID

        m_toolp->readGroupint(subGroup, "isFEFace", &isFEFace);
        m_toolp->readGroupint(subGroup, "OutsideNCTID", &OutsideNCTID);
        m_toolp->readGroupint(subGroup, "InsideNCTID", &InsideNCTID);
        m_toolp->readGroupDouble(subGroup, "OutsideNCTCoveredArea", &OutsideNCTCoveredArea);
        m_toolp->readGroupDouble(subGroup, "InsideNCTCoveredArea", &InsideNCTCoveredArea);
        m_toolp->readGroupint(subGroup, "ID", &ID);
        faceP->setFEFace(isFEFace == 1 ? true : false);
        faceP->setOutsideNCTID(OutsideNCTID);
        faceP->setInsideNCTID(InsideNCTID);
        faceP->setOutsideNCTCoveredArea(OutsideNCTCoveredArea);
        faceP->setInsideNCTCoveredArea(InsideNCTCoveredArea);

        Core::FITKAbstractDataIDAlter a;
        a.modifyDataID(faceP, ID);
        mager->appendDataObj(faceP);
    }
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::writeFace(H5::Group &gp, Acoustics::FITKSEAFaceManager * FaceManagerP)
{
    int count = FaceManagerP->getDataCount();//获取面管理器管理的面个数
    m_toolp->createAttribute(gp, "FaceDataCount", count);

    for (int i = 0; i < count; ++i)
    {
        Acoustics::FITKAbstractSEAFace *faceP = FaceManagerP->getDataByIndex(i);//获取每一个面
        if (faceP == nullptr) { return false; }

        QString number = QString::number(i);
        std::tuple<bool, H5::Group>Ret = m_toolp->createGp(gp, number.toStdString().data());//创建子节点
        if (std::get<0>(Ret) == false) { return false; }
        H5::Group subGroup = std::get<1>(Ret);

        QList<Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode> Nodes = faceP->getNodes();//子系统节点列表
        this->writeNodes(subGroup, Nodes);//写子系统节点列表

        Acoustics::FITKAcousticsTriangles*TriangleMesh = faceP->getTriangleMesh();//三角形列表
        if (TriangleMesh == nullptr) { return false; }

        this->writeTriangleMesh(subGroup, TriangleMesh);//写三角形列表
        bool isFEFace = faceP->isFEFace();//是否是使用 FE的面生成的
        int OutsideNCTID = faceP->getOutsideNCTID();//外部声学包id
        int InsideNCTID = faceP->getInsideNCTID();//内部声学包id
        double OutsideNCTCoveredArea = faceP->getOutsideNCTCoveredArea();//外部声学包覆盖率 0-100
        double InsideNCTCoveredArea = faceP->getInsideNCTCoveredArea();//内部声学包覆盖率 0-100
        int ID = faceP->getDataObjectID();//获取DataID
        m_toolp->writeGroupAttrInt(subGroup, "isFEFace", isFEFace == true ? 1 : 0);
        m_toolp->writeGroupAttrInt(subGroup, "OutsideNCTID", OutsideNCTID);
        m_toolp->writeGroupAttrInt(subGroup, "InsideNCTID", InsideNCTID);
        m_toolp->writeGroupAttrDouble(subGroup, "OutsideNCTCoveredArea", OutsideNCTCoveredArea);
        m_toolp->writeGroupAttrDouble(subGroup, "InsideNCTCoveredArea", InsideNCTCoveredArea);
        m_toolp->writeGroupAttrInt(subGroup, "ID", ID);
        this->writeTypeFace(subGroup, faceP);
    }
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::writeNodes(H5::Group & gp, QList<Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode> &Nodes)
{
    //一个面的节点列表
    std::tuple<bool, H5::Group>Ret = m_toolp->createGp(gp, "Nodes");//创建子节点
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group subGroup = std::get<1>(Ret);

    //在组下创建属性，并为附加数据个数属性
    m_toolp->createAttribute(subGroup, "NodesCount", Nodes.size());

    //写子系统节点列表
    std::vector<int>NodeidS;
    std::vector<int>types;
    for (int NodesIndex = 0; NodesIndex < Nodes.size(); ++NodesIndex)
    {
        Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode Node = Nodes.at(NodesIndex);
        int NodeId = Node._id;
        Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType Nodetype = Node._type;
        int NodeTypeStr = this->SubSysNodeTypeToInt(Nodetype);//枚举转int
        NodeidS.push_back(NodeId);
        types.push_back(NodeTypeStr);
    }
    m_toolp->CreateOneDarrayDataSetInt(subGroup, "NodeIds", NodeidS);
    m_toolp->CreateOneDarrayDataSetInt(subGroup, "types", types);
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::readNodes(H5::Group & gp, Acoustics::FITKAbstractSEAFace * faceP)
{
    if (faceP == nullptr)
    {
        return false;
    }
    //一个面的节点列表
    std::tuple<bool, H5::Group>Ret = m_toolp->openGp(gp, "Nodes");//打开子节点
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group subGroup = std::get<1>(Ret);


    std::tuple<bool, H5::Attribute>RetAttr = m_toolp->openAttribut(subGroup, "NodesCount"); //打开组个数属性
    if (std::get<0>(RetAttr) == false) { return false; }
    H5::Attribute CountAttrattr = std::get<1>(RetAttr);
    int count = -1;
    CountAttrattr.read(H5::PredType::NATIVE_INT, &count);

    std::vector<int>NodeidS;
    std::vector<int>types;

    m_toolp->ReadOneDArrayDataSetInt(subGroup, "NodeIds", NodeidS);
    m_toolp->ReadOneDArrayDataSetInt(subGroup, "types", types);

    if (NodeidS.size() != types.size())//大小根据写入时规定，一定一致，否则错误
    {
        return false;
    }

    QList<Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode> NodeList;

    for (int i = 0; i < count; i++)
    {
        Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode Node;
        Node._id = NodeidS.at(i);
        Node._type = this->IntFromSubSysNodeType(types.at(i));
        NodeList.push_back(Node);
    }
    faceP->setNodes(NodeList);
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::writeTriangleMesh(H5::Group & gp, Acoustics::FITKAcousticsTriangles * TriangleMesh)
{
    //一个面中的三角形
    if (TriangleMesh == nullptr)
    {
        return false;
    }

    std::tuple<bool, H5::Group>Ret = m_toolp->createGp(gp, "TriangleMesh");//创建子节点
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group subGroup = std::get<1>(Ret);

    int ElementCount = TriangleMesh->getElementCount();//单元数量

    if (m_isinit == false)
    {
        m_isinit = true;//如果已经分配了内存，就不重新分配了
        m_TriangleAllElementData.reserve(ElementCount);//复用容器分配内存
    }
    m_TriangleAllElementData.clear();//每次使用将个数清空，但空间不动
    for (int i = 0; i < ElementCount; ++i)
    {
        Interface::FITKAbstractElement* Element = TriangleMesh->getElementAt(i);
        if (Element == nullptr)
        {
            return false;
        }
        Interface::FITKModelEnum::FITKEleType type = Element->getEleType();//获取单元类型
        if (type != Interface::FITKModelEnum::FITKEleType::Tri3)
        {
            /*
            确认后，只会使用这一种类型，如果非这种类型就错误了,在读的时候就默认使用该类型
            该子类没有任何数据，所以只需存储父类数据FITKAbstractElement
            */
            return false;
        }
        int EleID = Element->getEleID();//单元ID 一般为-1 
        QList<int> Nodes = Element->getAllNodes();//所有节点
        std::vector<int>temp;
        temp.push_back(EleID);
        if (Nodes.size() != 3)
        {
            continue;
        }
        for (int i = 0; i < 3; i++)
        {
            temp.push_back(Nodes.at(i));
        }
        m_TriangleAllElementData.push_back(temp);
    }
    m_toolp->CreateTwoArrayDataSetInt(subGroup, "TriangleMeshData", m_TriangleAllElementData);
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::readTriangleMesh(H5::Group & gp, Acoustics::FITKAbstractSEAFace * faceP)
{
    if (faceP == nullptr)
    {
        return false;
    }
    //一个面的节点列表
    std::tuple<bool, H5::Group>Ret = m_toolp->openGp(gp, "TriangleMesh");//打开子节点
    if (std::get<0>(Ret) == false) { return false; }
    H5::Group subGroup = std::get<1>(Ret);


    Acoustics::FITKAcousticsTriangles*TriangleMeshP = faceP->getTriangleMesh();
    m_TriangleAllElementData.clear();//每次使用将个数清空，但空间不动
    m_toolp->ReadTwoArrayDataSetInt(subGroup, "TriangleMeshData", m_TriangleAllElementData);//继续复用

    for (int i = 0; i < m_TriangleAllElementData.size(); ++i)
    {
        Interface::FITKElementTri3 *Element = new Interface::FITKElementTri3;

        //读取数据[0]ID [1][2][3]NodesID 写的时候固定了格式，读的时候，不用判断
        std::vector<int>temp = m_TriangleAllElementData.at(i);
        int EleID = temp.at(0);
        QList<int>Nodes;
        Nodes.append(temp.at(1));
        Nodes.append(temp.at(2));
        Nodes.append(temp.at(3));

        //设置数据
        Element->setEleID(EleID);
        Element->setNodeID(Nodes);
        TriangleMeshP->appendElement(Element);
    }
    return true;
}

bool IO::FITKAcousticsSEAFaceMgrAdaptor::writeTypeFace(H5::Group & gp, Acoustics::FITKAbstractSEAFace * faceP)
{
    if (faceP == nullptr)
    {
        return false;
    }
    Acoustics::FITKAbstractSEASubSys::SEASubSysType faceType = faceP->getFaceType();//获取面类型
    //目前只有双曲率板有额外的数据

    std::string typeStr = "";

    switch (faceType)
    {
    case Acoustics::FITKAbstractSEASubSys::SEASSNone:
    {
        typeStr = "SEASSNone";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEABeam:
    {
        //梁面
        typeStr = "SEABeam";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEAFlatPlate:
    {
        //平板
        typeStr = "SEAFlatPlate";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell:
    {
        //单曲率板
        typeStr = "SEASinglyCurvedShell";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell:
    {

        //双曲率板
        typeStr = "SEADoublyCurvedShell";
        Acoustics::FITKSEADoublyCurvedFace* ObjP = dynamic_cast<Acoustics::FITKSEADoublyCurvedFace*>(faceP);//转换子类
        if (ObjP == nullptr)
        {
            return false;
        }
        int NumberOfRing = ObjP->getNumberOfRing();//获取环数
        m_toolp->writeGroupAttrInt(gp, "NumberOfRing", NumberOfRing);
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEACylinderShell:
    {
        typeStr = "SEACylinderShell";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEACavity:
    {
        typeStr = "SEACavity";
        break;
    }

    case Acoustics::FITKAbstractSEASubSys::SEASemiIInfiniteFluid:
    {
        typeStr = "SEASemiIInfiniteFluid";
        break;
    }

    default:
        typeStr = "SEASSNone";
        break;
    }
    m_toolp->writeGroupAttrStr(gp, "FaceType", typeStr);//写类型

    return true;
}

Acoustics::FITKAbstractSEASubSys::SEASubSysType IO::FITKAcousticsSEAFaceMgrAdaptor::readTypeFace(H5::Group & gp)
{
    std::string type;
    m_toolp->readGroupStr(gp, "FaceType", type);
    if (type == "SEASSNone")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEASSNone;
    }
    else if (type == "SEABeam")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEABeam;
    }    if (type == "SEAFlatPlate")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEAFlatPlate;
    }
    else if (type == "SEASinglyCurvedShell")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEASinglyCurvedShell;
    }
    else if (type == "SEADoublyCurvedShell")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEADoublyCurvedShell;
    }
    else if (type == "SEACylinderShell")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEACylinderShell;
    }
    else if (type == "SEACavity")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEACavity;
    }
    else if (type == "SEASemiIInfiniteFluid")
    {
        return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEASemiIInfiniteFluid;
    }

    return Acoustics::FITKAbstractSEASubSys::SEASubSysType::SEASSNone;
}

int IO::FITKAcousticsSEAFaceMgrAdaptor::SubSysNodeTypeToInt(Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType Nodetype)
{
    switch (Nodetype)
    {
    case Acoustics::FITKAbstractSEASubSysWithNodes::None:
    {
        return 1;
        break;
    }

    case Acoustics::FITKAbstractSEASubSysWithNodes::Start:
    {
        return 2;
        break;
    }

    case Acoustics::FITKAbstractSEASubSysWithNodes::Path:
    {
        return 3;
        break;
    }
    case Acoustics::FITKAbstractSEASubSysWithNodes::Corner:
    {
        return 4;
        break;
    }
    case Acoustics::FITKAbstractSEASubSysWithNodes::Finish:
    {
        return 5;
        break;
    }
    default:
    {
        return 1;
        break;
    }
    }
}

Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType IO::FITKAcousticsSEAFaceMgrAdaptor::IntFromSubSysNodeType(int  Nodetype)
{
    if (Nodetype == 1)
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::None;
    }
    else if (Nodetype == 2)
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Start;
    }
    else if (Nodetype == 3)
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Path;
    }
    else if (Nodetype == 4)
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Corner;
    }
    else if (Nodetype == 5)
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::Finish;
    }
    else
    {
        return Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNodeType::None;
    }
}
